package com.hsmw.api.service;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.hsmw.api.controller.pub.WebSocket;
import com.hsmw.api.mapper.HsmwDriverUserMapper;
import com.hsmw.api.mapper.HsmwOrderBalanceMapper;
import com.hsmw.api.mapper.HsmwUserDriverMapper;
import com.hsmw.api.vo.DriverDetailInfoVO;
import com.hsmw.api.vo.DriverOrderRecordDTO;
import com.hsmw.api.vo.DriverRegisterPageVO;
import com.hsmw.api.vo.WebSocketReturnVO;
import com.hsmw.api.utils.CommonUtils;
import com.htn.common.core.base.DataResponse;
import com.htn.common.core.constant.ChildOrderStatusEnum;
import com.htn.common.core.constant.CommonConstants;
import com.htn.common.core.constant.WebsocketTypeEnum;
import com.hsmw.domain.*;
import com.hsmw.domain.vo.DriverUserVO;
import com.hsmw.common.base.BaseService;
import com.hsmw.domain.vo.DriverDetailVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@Service
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class HsmwDriverUserService extends BaseService<HsmwDriverUserMapper,HsmwDriverUser> {


    @Autowired
    private HsmwDriverUserMapper hsmwDriverUserMapper;


    @Autowired
    private HsmwUserDriverMapper hsmwUserDriverMapper;

    @Autowired
    private HsmwLeasingCompanyService hsmwLeasingCompanyService;

    @Autowired
    private HsmwVehicleService hsmwVehicleService;

    @Autowired
    private HsmwDriverUserService hsmwDriverUserService;

    @Autowired
    private HsmwItemService hsmwItemService;

    @Autowired
    private WebSocket webSocket;

    @Autowired
    private HsmwOrderBalanceMapper hsmwOrderBalanceMapper;

    @Autowired
    private HsmwDriverOrderRecordService hsmwDriverOrderRecordService;

    @Autowired
    private HsmwRunSprintRecordService hsmwRunSprintRecordService;


    public HsmwDriverUser findByUsername(String username) {
        QueryWrapper<HsmwDriverUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(HsmwDriverUser::getUsername, username);
        return hsmwDriverUserMapper.selectOne(queryWrapper);
    }

    public void saveOrUpdateUser(HsmwDriverUser hsmwUser) {
        if(StringUtils.isNotBlank(hsmwUser.getId())){
            hsmwUser.setEnabled(true);
            hsmwUser.setAvatar(hsmwUser.getQueryParam());
            hsmwDriverUserMapper.updateById(hsmwUser);
            HsmwUserDriver hsmwUserDriver = hsmwUserDriverMapper.selectOne(new LambdaQueryWrapper<HsmwUserDriver>().eq(HsmwUserDriver::getUserId, hsmwUser.getId()));
            hsmwUserDriver.setMyPicture(hsmwUser.getQueryParam());
            hsmwUserDriverMapper.updateById(hsmwUserDriver);
        }else {
            hsmwDriverUserMapper.insert(hsmwUser);
        }
    }
    public IPage<DriverRegisterPageVO> getDriverRegisterPage(IPage page, DriverRegisterPageVO driverRegisterPageVo) {
        IPage<DriverRegisterPageVO> ipage = hsmwDriverUserMapper.getDriverRegisterPage(page, driverRegisterPageVo.getUsername(), driverRegisterPageVo.getIsDriver());
        return ipage;
    }

    public List<DriverDetailVO> findDriverInfo(HashMap param) {
        return  hsmwDriverUserMapper.findDriverInfo(param);
    }

    public DriverUserVO findDriverUserById(String userId) {

        return hsmwDriverUserMapper.findDriverUserById(userId);
    }

    public DataResponse addDriverOrderRecordInfoByDriver(DriverOrderRecordDTO driverOrderRecordDTO) {

        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        //要求到达时间
        LocalDateTime reachTime = LocalDateTime.parse(driverOrderRecordDTO.getStartTime(),df);
        //实际到达时间
        LocalDateTime realReachTime = LocalDateTime.parse(driverOrderRecordDTO.getStartTime(),df);
        //结束时间
        LocalDateTime endTime = LocalDateTime.parse(driverOrderRecordDTO.getEndTime(),df);

        // 司机方量
        Double driverVolume = Double.valueOf(driverOrderRecordDTO.getDriverVolume());
        LocalDateTime startWorkTime = null;
        Double workTime = 0.0;
        Double formulaTime = 0.0;
        String settlementVolume ="";

        String userName = "";

        HsmwOrderBalance hsmwOrderBalance = new HsmwOrderBalance();
        String orderid = CommonUtils.generateId(hsmwOrderBalance);
        List<HsmwDriverOrderRecord> records = new ArrayList<>();
        List<HsmwRunSprintRecord> runSprintRecords = new ArrayList<>();

        List<DriverDetailInfoVO> driverDetailInfoVOList = driverOrderRecordDTO.getDriverDetailInfoVOList();
        for (DriverDetailInfoVO driverDetailInfoVO : driverDetailInfoVOList) {
            if(StringUtils.isNotBlank(driverDetailInfoVO.getDriverId())){
                //查询司机信息
                HsmwUserDriver userDriver = hsmwUserDriverMapper.selectById(driverDetailInfoVO.getDriverId());
                //查询车辆信息
                HsmwVehicle hsmwVehicle = hsmwVehicleService.getById(driverOrderRecordDTO.getVehicleId());

                //判断司机是否属于天津邵濮集团 属于邵濮集团的按照邵濮的规则进行计算 不属于邵濮 按照别的方式进行计算
                if(userDriver != null  && StringUtils.isNotBlank(userDriver.getOwnCompanyId())){
                    HsmwLeasingCompany company = hsmwLeasingCompanyService.getById(userDriver.getOwnCompanyId());
                    if(company != null && StringUtils.isNotBlank(company.getName())){
                        if(com.htn.common.core.utils.StringUtils.equals("天津邵濮集团",company.getName())){
                            //实际到达时间小于要求到达时间 工作时间为：要求到达时间后的两个小时
                            if(realReachTime != null){
                                if(realReachTime.isBefore(reachTime) || realReachTime.equals(reachTime)){
                                    startWorkTime = (reachTime.plusHours(2));
                                    // 司机提交的方量不为0 在进行计算结算方量  为0 则结算放量也为0
                                    if(driverVolume != 0.0){
                                        if(endTime != null){
                                            Long endTimeSecond  = endTime.toEpochSecond(ZoneOffset.of("+8"));
                                            Long reachTimeSecond  = startWorkTime.toEpochSecond(ZoneOffset.of("+8"));
                                            Double hours = 0.0;
                                            if((endTimeSecond-reachTimeSecond)%3600>0){
                                                BigDecimal bd = new BigDecimal((endTimeSecond - reachTimeSecond));
                                                bd = bd.setScale(2,BigDecimal.ROUND_HALF_UP);
                                                BigDecimal divide = bd.divide(new BigDecimal("3600"), BigDecimal.ROUND_HALF_UP);
                                                long value = (endTimeSecond - reachTimeSecond) / 3600;
                                                BigDecimal subtract = divide.subtract(new BigDecimal(value));
                                                //hours = ( / 3600) + 1;
                                                if(subtract.compareTo(new BigDecimal("0.5")) == 1){
                                                    hours = ((endTimeSecond - reachTimeSecond) / 3600) + 1.0;
                                                }else {
                                                    hours = ((endTimeSecond - reachTimeSecond) / 3600) + 0.5;
                                                }
                                            }else {
                                                hours = ((endTimeSecond - reachTimeSecond) / 3600.00);
                                            }
                                            workTime = hours;
                                            Long forTime = startWorkTime.toEpochSecond(ZoneOffset.of("+8"));
                                            Double forHours = 0.0;
                                            if((endTimeSecond - forTime)%3600 > 0){
                                                BigDecimal bd = new BigDecimal((endTimeSecond - forTime));
                                                bd = bd.setScale(2,BigDecimal.ROUND_HALF_UP);
                                                BigDecimal divide = bd.divide(new BigDecimal("3600"), BigDecimal.ROUND_HALF_UP);
                                                long value = (endTimeSecond - forTime) / 3600;
                                                BigDecimal subtract = divide.subtract(new BigDecimal(value));
                                                //hours = ( / 3600) + 1;
                                                if(subtract.compareTo(new BigDecimal("0.5")) == 1){
                                                    forHours = ((endTimeSecond - reachTimeSecond) / 3600) + 1.0;
                                                }else {
                                                    forHours = ((endTimeSecond - reachTimeSecond) / 3600) + 0.5;
                                                }

                                            }else {
                                                forHours = ((endTimeSecond - forTime) / 3600.0);
                                            }
                                            formulaTime = forHours;
                                            if(hours > 10){
                                                Double aLong = 100.0;
                                                aLong = aLong + (hours - 10)*10;
                                                if(aLong > driverVolume){
                                                    settlementVolume=String.valueOf(aLong);
                                                }else {
                                                    settlementVolume=String.valueOf(driverVolume);
                                                }
                                            }else {
                                                Long aLong = 100L;
                                                if(aLong > driverVolume){
                                                    settlementVolume=String.valueOf(aLong);
                                                }else {
                                                    settlementVolume=String.valueOf(driverVolume);
                                                }
                                            }
                                        }
                                    }else {
                                        settlementVolume="0";
                                        hsmwOrderBalance.setRunCount("1");
                                    }
                                }else {
                                    startWorkTime = (realReachTime.plusHours(2));
                                    //反之，为实际到达时间后两个小时
                                    //结束时间 减去 上述开始时间 如果大于10小时 如：十三个小时 一个小时保底为 10，不满一个小时按照一个小时计算
                                    if(driverVolume != 0){
                                        if(endTime != null){
                                            Long endTimeSecond  = endTime.toEpochSecond(ZoneOffset.of("+8"));
                                            Long realReachTimeSecond  = startWorkTime.toEpochSecond(ZoneOffset.of("+8"));
                                            Double hours = 0.0;
                                            if((endTimeSecond-realReachTimeSecond)%3600>0){
                                                BigDecimal bd = new BigDecimal((endTimeSecond - realReachTimeSecond));
                                                bd = bd.setScale(2,BigDecimal.ROUND_HALF_UP);
                                                BigDecimal divide = bd.divide(new BigDecimal("3600"), BigDecimal.ROUND_HALF_UP);
                                                long value = (endTimeSecond - realReachTimeSecond) / 3600;
                                                BigDecimal subtract = divide.subtract(new BigDecimal(value));
                                                //hours = ( / 3600) + 1;
                                                if(subtract.compareTo(new BigDecimal("0.5")) == 1){
                                                    hours = ((endTimeSecond - realReachTimeSecond) / 3600) + 1.0;
                                                }else {
                                                    hours = ((endTimeSecond - realReachTimeSecond) / 3600) + 0.5;
                                                }
                                            }else {
                                                hours = ((endTimeSecond - realReachTimeSecond) / 3600.0);
                                            }
                                            workTime = hours;
                                            Long forTime = startWorkTime.toEpochSecond(ZoneOffset.of("+8"));
                                            Double forHours = 0.0;
                                            if((endTimeSecond - forTime)%3600 > 0){
                                                BigDecimal bd = new BigDecimal((endTimeSecond - forTime));
                                                bd = bd.setScale(2,BigDecimal.ROUND_HALF_UP);
                                                BigDecimal divide = bd.divide(new BigDecimal("3600"), BigDecimal.ROUND_HALF_UP);
                                                long value = (endTimeSecond - forTime) / 3600;
                                                BigDecimal subtract = divide.subtract(new BigDecimal(value));
                                                //hours = ( / 3600) + 1;
                                                if(subtract.compareTo(new BigDecimal("0.5")) == 1){
                                                    forHours = ((endTimeSecond - forTime) / 3600) + 1.0;
                                                }else {
                                                    forHours = ((endTimeSecond - forTime) / 3600) + 0.5;
                                                }
                                            }else {
                                                forHours = ((endTimeSecond - forTime) / 3600.0);
                                            }
                                            formulaTime = forHours;
                                            if(hours > 10){
                                                Double aLong = 100.0;
                                                aLong = aLong + (hours - 10)*10;
                                                if(aLong > driverVolume){
                                                    settlementVolume=String.valueOf(aLong);
                                                }else {
                                                    settlementVolume=String.valueOf(driverVolume);
                                                }
                                            }else {
                                                Long aLong = 100L;
                                                if(aLong > driverVolume){
                                                    settlementVolume=String.valueOf(aLong);
                                                }else {
                                                    settlementVolume=String.valueOf(driverVolume);
                                                }
                                            }
                                        }else {
                                            settlementVolume="0";
                                        }
                                    }else {
                                        settlementVolume="0";
                                        hsmwOrderBalance.setRunCount("1");
                                    }
                                }
                            }else {
                                settlementVolume="0";
                            }

                            if(workTime < 0){
                                workTime = 0.0;
                            }
                            workTime = workTime+2;
                        }else {
                            // 其他公司
                            Long endTimeSecond  = endTime.toEpochSecond(ZoneOffset.of("+8"));
                            Long reachTimeSecond  = realReachTime.toEpochSecond(ZoneOffset.of("+8"));
                            settlementVolume= driverOrderRecordDTO.getDriverVolume();
                            double value = ((endTimeSecond - reachTimeSecond) / 3600);
                            workTime = value;
                        }
                    }
                } // end 结束规则判断

                // 查询司机的 个人信息
                HsmwDriverUser driverUser = hsmwDriverUserService.getById(userDriver.getUserId());
                //根据司机userid 查询司机姓名
                if(com.htn.common.core.utils.StringUtils.isNotBlank(driverUser.getName())){
                    userName += driverUser.getName()+"、";
                }
                HsmwDriverOrderRecord record1 = new HsmwDriverOrderRecord();
                record1.setVehicleType(hsmwVehicle.getVehicleType());
                record1.setVehicleModel(hsmwVehicle.getVehicleModel());
                record1.setDriverId(userDriver.getId());
                record1.setOrderId(orderid);
                record1.setVehicleNum(hsmwVehicle.getVehiclePlate());
                record1.setVehicleId(hsmwVehicle.getId());
                record1.setOrderStatus(ChildOrderStatusEnum.COMPLETED.getValue());
                record1.setRealVolume(String.valueOf(driverVolume));
                record1.setSettlementVolume(settlementVolume);
                record1.setRemark("线下");
                record1.setEndTime(endTime);
                record1.setItemName(driverOrderRecordDTO.getItemName());
                record1.setItemPosition(driverOrderRecordDTO.getItemPosition());
                record1.setStartWorkTime(reachTime);
                record1.setConstructionPosition(driverOrderRecordDTO.getConstructionPosition());
                record1.setConstructionUnitName(driverOrderRecordDTO.getConstructionUnitName());
                record1.setMovePumpCount(driverOrderRecordDTO.getMovePumpCount());
                record1.setWorkTime(String.valueOf(workTime));
                record1.setItemId(driverOrderRecordDTO.getItemId());
                record1.setChassisKilometers(driverOrderRecordDTO.getChassisKilometers());
                //2.2 添加的几个字段
                record1.setScore(userDriver.getScore());
                record1.setYears(hsmwVehicle.getYears());
                record1.setArmSegment(hsmwVehicle.getArmSegment());
                record1.setVehicleBrand(hsmwVehicle.getVehicleBrand());
                record1.setAxis(hsmwVehicle.getAxis());
                record1.setVehicleLeftImage(hsmwVehicle.getVehicleLeftImage());
                record1.setVehicleRightImage(hsmwVehicle.getVehicleRightImage());
                record1.setDriverUserId(userDriver.getUserId());
                record1.setChassisBrand(hsmwVehicle.getChassisBrand());
                record1.setTrafficRate(hsmwVehicle.getTrafficRate());
                records.add(record1);

                // 判断司机的填写的方量是不是为 0  0就是空跑订单
                if(driverVolume == 0.0){
                    HsmwRunSprintRecord hsmwRunSprintRecord = new HsmwRunSprintRecord();
                    hsmwRunSprintRecord.setOrderId(orderid);
                    hsmwRunSprintRecord.setFlag("2");
                    hsmwRunSprintRecord.setDriverId(userDriver.getId());
                    runSprintRecords.add(hsmwRunSprintRecord);

                    WebSocketReturnVO webSocketReturnVO = new WebSocketReturnVO();
                    webSocketReturnVO.setStatus(WebsocketTypeEnum.ZERO_ORDER.getValue());
                    webSocketReturnVO.setMessage("您填写的方量是0m³，系统为您判断成为空跑订单。");
                    String returnJson = JSONObject.toJSON(webSocketReturnVO).toString();
                    webSocket.AppointSending(driverUser.getUsername(), returnJson);
                }
            }
        } // end 循环结束

        //查询司机信息
        HsmwUserDriver userDriver = hsmwUserDriverMapper.selectById(driverDetailInfoVOList.get(0).getDriverId());
        HsmwVehicle hsmwVehicle = hsmwVehicleService.getById(driverOrderRecordDTO.getVehicleId());

        hsmwOrderBalance.setDriverName(userName.substring(0,userName.length()-1));
        hsmwOrderBalance.setCarNum(hsmwVehicle.getCarNum());
        hsmwOrderBalance.setVehicleType(hsmwVehicle.getVehicleType());
        hsmwOrderBalance.setConstructionUnitName(driverOrderRecordDTO.getConstructionUnitName());
        hsmwOrderBalance.setConstructionPosition(driverOrderRecordDTO.getConstructionPosition());
        hsmwOrderBalance.setItemId(driverOrderRecordDTO.getItemId());
        hsmwOrderBalance.setItemName(driverOrderRecordDTO.getItemName());
        hsmwOrderBalance.setRealVolume(String.valueOf(driverVolume));
        hsmwOrderBalance.setSettlementVolume(String.valueOf(settlementVolume));
        hsmwOrderBalance.setMovePumpCount(driverOrderRecordDTO.getMovePumpCount());
        hsmwOrderBalance.setFormulaTime(String.valueOf(formulaTime));
        hsmwOrderBalance.setStartWorkTime(realReachTime);
        hsmwOrderBalance.setEndTime(endTime);
        hsmwOrderBalance.setWorkTime(String.valueOf(workTime+2));
        hsmwOrderBalance.setStatementsTime(LocalDateTime.now());
        hsmwOrderBalance.setOrderId(records.get(0).getOrderId());
        HsmwLeasingCompany company = hsmwLeasingCompanyService.getById(userDriver.getOwnCompanyId());

        if(com.htn.common.core.utils.StringUtils.isNotNull(company)){
            hsmwOrderBalance.setRunSubsidy(company.getSubsidyAmount());
            hsmwOrderBalance.setMovePumpSubsidy(company.getMovePumpSubsidy());
        }

        hsmwOrderBalance.setConcreteNum("线下录入,无混凝土标号信息");
        hsmwOrderBalance.setVehicleId(hsmwVehicle.getId());
        hsmwOrderBalance.setDriverId(userDriver.getId());
        hsmwOrderBalance.setConstructionTime(LocalDate.now());
        hsmwOrderBalance.setOrderStatus("6");
        hsmwOrderBalance.setVehicleNum(hsmwVehicle.getVehiclePlate());
        HsmwItem hsmwItem = hsmwItemService.getById(driverOrderRecordDTO.getItemId());
        if(com.htn.common.core.utils.StringUtils.isNotNull(hsmwItem) && com.htn.common.core.utils.StringUtils.isNotBlank(hsmwItem.getSettlementPrice())){
            if(com.htn.common.core.utils.StringUtils.equals("0",hsmwItem.getSettlementPrice())){
                hsmwOrderBalance.setMonovalent("0");
                hsmwOrderBalance.setMoney("0");
            }else {
                DecimalFormat dfc = new DecimalFormat("#.0");
                hsmwOrderBalance.setMonovalent(hsmwItem.getSettlementPrice());
                Double monovalent = Double.valueOf(hsmwOrderBalance.getMonovalent());
                String money = dfc.format(driverVolume * monovalent);
                if(com.htn.common.core.utils.StringUtils.equals(".0",money)){
                    money = "0";
                }
                hsmwOrderBalance.setMoney(money);
            }
        }
        hsmwOrderBalance.setDifferenceVolume(String.valueOf(driverVolume));
        if(com.htn.common.core.utils.StringUtils.isNotBlank(hsmwOrderBalance.getWriteVolume()) && !com.htn.common.core.utils.StringUtils.equals("0",hsmwOrderBalance.getWriteVolume())){
            hsmwOrderBalance.setOutputVolume(hsmwOrderBalance.getWriteVolume());
        }else {
            hsmwOrderBalance.setOutputVolume(hsmwOrderBalance.getRealVolume());
        }
        hsmwOrderBalanceMapper.insert(hsmwOrderBalance);
        boolean rec = hsmwDriverOrderRecordService.saveBatch(records);
        hsmwRunSprintRecordService.saveBatch(runSprintRecords);
        if(rec){
            return new DataResponse(CommonConstants.ResponseStatus.SUCCESS);
        }
        return new DataResponse(CommonConstants.ResponseStatus.FAIL);
    }
}
